import { Get, Controller, Body, Post, Res } from '@nestjs/common';
import type { Response } from 'express';
import { AiService } from './ai.service';
import { GisGetInfoDto } from './dto/gis-modal';
import { createSSEData, initThreadId } from './utils/common';
import { streamText, generateText } from 'ai';
import { createDeepSeek } from '@ai-sdk/deepseek';
import { START, END, StateGraph, Annotation } from '@langchain/langgraph';
import { BaseMessage, HumanMessage } from '@langchain/core/messages';
import {
  getAliAgent,
  getQwenAgentInstance,
  getQwenImageAgentInstance,
} from './llm/agentList';
const deepseek = createDeepSeek({
  baseURL: 'https://api.deepseek.com/v1',
  apiKey: 'sk-50c04cd0ad5b4d45a0198b38610d9fb8',
});
@Controller('ai')
export class AiController {
  constructor(private readonly aiService: AiService) {}

  @Get('/')
  hello() {
    return 'this is ai';
  }

  @Post('/chat/01')
  async test01(@Body() body: GisGetInfoDto, @Res() res: Response) {
    console.log('body>>111', JSON.stringify(body, null, 2));
    const { messagesList, modelConfig } = body;
    const chatSessionId = body.chatSessionId || 'gis-session-' + initThreadId();

    const result = await this.aiService.test01();
    console.log('result>>', result);
    if (result instanceof ReadableStream) {
      // 流式响应
      res.writeHead(200, { 'Content-Type': 'text/event-stream' });

      // 将流式数据写入响应
      const reader = result.getReader();

      const pump = async () => {
        while (true) {
          const { done, value } = await reader.read();
          console.log(done, value, 'done');
          if (done) {
            res.end();
            break;
          }
          res.write(value);
        }
      };

      await pump();
    }
  }
  @Post('/chat/02')
  async test02(@Body() body: GisGetInfoDto, @Res() res: Response) {
    console.log('body>>111', JSON.stringify(body, null, 2));

    const resp = streamText({
      model: deepseek('deepseek-chat'),
      prompt: '1+1',
    });
    res.writeHead(200, { 'Content-Type': 'text/event-stream' });

    // 方式1：使用textStream获取纯文本增量[4](@ref)
    for await (const textPart of resp.textStream) {
      console.log(textPart); // 逐部分打印文本
      res.write(createSSEData({ type: 'chunk', text: textPart }));
    }
    res.write(createSSEData({ done: true }));
    res.end();
  }
  @Post('/chat/03')
  async test03(@Body() body: GisGetInfoDto) {
    console.log('body>>111', JSON.stringify(body, null, 2));
    const resp = await generateText({
      model: deepseek('deepseek-chat'),
      prompt: '使用中文回答我: 根号3有什么意义',
    });
    return resp.steps[0].content;
  }
  @Post('/chat/04')
  async test04(@Body() body: GisGetInfoDto) {
    const StateAnnotation = Annotation.Root({
      sentiment: Annotation<string>,
      resMsg: Annotation<string>({
        // 自定义 reducer 函数，用于合并多个节点返回的 resMsg 字段
        reducer: (left: string, right: string) => {
          return left + right;
        },
        // 默认值
        default: () => '',
      }),
      messages: Annotation<BaseMessage[]>({
        reducer: (left: BaseMessage[], right: BaseMessage | BaseMessage[]) => {
          if (Array.isArray(right)) {
            return left.concat(right);
          }
          return left.concat([right]);
        },
        default: () => [],
      }),
    });

    const workflow = new StateGraph(StateAnnotation)
      .addNode('node1', (state) => {
        //以下return 的值会被合并到state中,键必须在StateAnnotation中定义
        return {
          resMsg: 'zs',
          messages: [{ content: 'zs', id: 'x01' }] as BaseMessage[],
        };
      })
      .addNode('node2', (state) => {
        console.log('node2', state);

        return {
          resMsg: 'ls',
          messages: [{ content: 'ls', id: 'x02' }] as BaseMessage[],
        };
      });
    workflow
      .addEdge(START, 'node1')
      .addEdge('node1', 'node2')
      .addEdge('node2', END);
    const _agent = workflow.compile();
    const response = await _agent.invoke({
      messages: [new HumanMessage('how are you?')],
    });

    console.log('response>>>', response);
    return response;
  }
  @Post('/chat/05')
  async test05(@Body() body: GisGetInfoDto) {
    const StateAnnotation = Annotation.Root({
      ipt: Annotation<string>(),
      //天气
      weather: Annotation<string>({
        reducer: (left: string, right: string) => {
          return right; // 取最后一个节点的天气结果
        },
        default: () => '',
      }),
      //故事
      story: Annotation<string>({
        reducer: (left: string, right: string) => {
          return left + '\n' + right; // 合并各节点的故事内容
        },
        default: () => '',
      }),
      imageUrls: Annotation<{ url: string }[]>,
    });

    const workflow = new StateGraph(StateAnnotation)
      .addNode('weatherAgent', async (state) => {
        //以下return 的值会被合并到state中,键必须在StateAnnotation中定义
        const agent = await getQwenAgentInstance();
        const response = await agent.invoke({
          //   messages: [{ role: 'system', content: '使用中文回答' }],
          // messages: [new HumanMessage(`请告诉我${state.ipt}的天气情况`)],
          messages: [new HumanMessage(`请告诉我${state.ipt}的天气情况`)],
        });

        const content = response.messages.at(-1).content || '';
        console.log('>>>>>weatherAgent', content);
        return {
          weather: content,
          // resMsg: 'zs',
          // messages: [{ content: 'zs', id: 'x01' }] as BaseMessage[],
        };
      })
      .addNode('node2', async (state) => {
        // const agent = getQwenImageAgentInstance();
        // const res = await agent.invoke({
        //   // messages: [
        //   //   new HumanMessage(
        //   //     `请根据以下天气情况，生成一段描述${state.ipt}的图片，用于图片生成。天气情况是：${state.weather}`,
        //   //   ),
        //   // ],
        const prompt = `请根据以下天气情况，生成一幅山水画，突出季节变化，人们旅游场景，不需要展示温度日期。天气情况是：${state.weather}`;
        const prompt2 = `请根据以下天气情况，生成一个视频，突出季节变化，人们旅游场景，不需要展示温度日期。天气情况是：${state.weather}`;
        // });
        // const res1 = await fetch(
        //   'https://api.siliconflow.cn/v1/images/generations',
        //   {
        //     method: 'POST',
        //     headers: {
        //       'Content-Type': 'application/json',
        //       Authorization:
        //         'Bearer sk-sssdueysiwnoinzwqvtwhbwzdniszusgvprzrcaavppoocnb',
        //     },
        //     body: JSON.stringify({
        //       model: 'Qwen/Qwen-Image',
        //       prompt: prompt,
        //     }),
        //   },
        // ).then(async (res) => await res.json());
        // "url": "https://bizyair-prod.oss-cn-shanghai.aliyuncs.com/outputs%2F54876e97-d86f-4da8-a32c-cf766aa94f71_772f12d25dc4a98b224f157378803d9c_ComfyUI_9d88d8d8_00001_.png?OSSAccessKeyId=LTAI5tPza7RAEKed35dCML5U&Expires=1761413520&Signature=LgqJ%2B%2FYWq%2FTTKUoY%2FY8oAW6X7KA%3D"

        // const res = await fetch('https://api.siliconflow.cn/v1/video/submit', {
        //   method: 'POST',
        //   headers: {
        //     'Content-Type': 'application/json',
        //     Authorization:
        //       'Bearer sk-sssdueysiwnoinzwqvtwhbwzdniszusgvprzrcaavppoocnb',
        //   },
        //   body: JSON.stringify({
        //     model: 'an-AI/Wan2.1-I2V-14B-720P',
        //     prompt: prompt2,
        //     image_size: '1280x720',
        //   }),
        // }).then(async (res) => await res.json());
        const res = await fetch('https://aigc.sankuai.com/v1/wanx/tasks', {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json',
            Authorization: 'Bearer 1893979178723389537',
          },
          body: JSON.stringify({
            model: 'wanx2.1-i2v-turbo',
            input: {
              prompt: '一个天气图',
              img_url:
                'https://bizyair-prod.oss-cn-shanghai.aliyuncs.com/outputs%2F54876e97-d86f-4da8-a32c-cf766aa94f71_772f12d25dc4a98b224f157378803d9c_ComfyUI_9d88d8d8_00001_.png?OSSAccessKeyId=LTAI5tPza7RAEKed35dCML5U&Expires=1761413520&Signature=LgqJ%2B%2FYWq%2FTTKUoY%2FY8oAW6X7KA%3D',
            },
            parameters: {
              resolution: '720P',
              prompt_extend: true,
            },
          }),
        }).then(async (res) => await res.json());

        return {
          imageUrls: res || 'xxx://image-url.com/sample.jpg',
        };
      });
    workflow
      .addEdge(START, 'weatherAgent')
      .addEdge('weatherAgent', 'node2')
      .addEdge('node2', END);
    const _agent = workflow.compile();
    const response = await _agent.invoke({
      ipt: '北京',
    });

    // console.log('response>>>', response);
    // const agent = await getQwenAgentInstance();

    return response;
  }
  @Post('/chat/06')
  async test06(@Body() body: GisGetInfoDto, @Res() res: Response) {
    res.writeHead(200, { 'Content-Type': 'text/event-stream' });

    const StateAnnotation = Annotation.Root({
      ipt: Annotation<string>(),
      //天气
      weather: Annotation<string>({
        reducer: (left: string, right: string) => {
          return right; // 取最后一个节点的天气结果
        },
        default: () => '',
      }),
      //故事
      story: Annotation<string>({
        reducer: (left: string, right: string) => {
          return left + '\n' + right; // 合并各节点的故事内容
        },
        default: () => '',
      }),
      node2Text: Annotation<string[]>({
        reducer: (left: string[], right: string[]) => {
          left.push(...right);
          return left;
        },
        default: () => [],
      }),
      stepNum: Annotation<number>({
        reducer: (left: number, right: number) => {
          return right;
        },
        default: () => 0,
      }),
    });

    const workflow = new StateGraph(StateAnnotation)
      .addNode('weatherAgent', async (state) => {
        const agent = await getQwenAgentInstance();
        const response = await agent.stream(
          {
            messages: [new HumanMessage(`请告诉我${state.ipt}的天气情况`)],
          },
          { streamMode: 'messages' },
        );
        let txt = '';
        for await (const chunk of response) {
          const [messageChunk] = chunk;
          txt = txt + (messageChunk.content as string);
          res.write(createSSEData({ type: 'weatherAgent', text: txt }));
        }
        return { weather: txt };
      })
      .addNode('node2', async (state) => {
        const prompt = `请根据以下天气情况，生成一首诗。天气情况是：${state.weather}`;
        const agent = getAliAgent();
        const chunk = await agent.invoke(
          { messages: [new HumanMessage(prompt)] },
          // { streamMode: 'messages' },
        );
        /** 默认是 values
         * { streamMode: 'values' },--->res.messages[chunk.messages.length - 1].content,
         *{ streamMode: 'messages' },--->res[0][0].content
         */
        // console.log('>>>>>chunk', JSON.stringify(chunk, null, 2), '>>>');
        res.write(
          createSSEData({
            type: 'node2Text-' + state.stepNum,
            text: chunk.messages[chunk.messages.length - 1].content,
          }),
        );

        return {
          node2Text: [chunk.messages[chunk.messages.length - 1].content],
          stepNum: state.stepNum + 1,
        };
      });
    // 添加节点
    workflow.addEdge(START, 'weatherAgent').addEdge('weatherAgent', 'node2');
    //添加条件边
    workflow.addConditionalEdges(
      'node2',
      (state) => {
        if (state.stepNum < 3) {
          return 'node2';
        } else {
          return 'end';
        }
      },
      { node2: 'node2', end: END },
    );
    workflow.addEdge('node2', END);
    const _agent = workflow.compile();
    const response = await _agent.invoke({ ipt: '上海' });

    res.end(createSSEData({ type: 'end', text: response }));
  }
}
